As programs continue to increase in size and data handling, more effective means for managing memory and reducing overhead become a necessity. Garbage collection is one mechanism for reclaiming memory used by objects of an application that will not be used again by that application.
Many garbage collectors and other runtime systems require that special code is executed during modification or access of memory locations that may contain pointer values. Moreover, some garbage collectors introduce an overhead on any memory access (not only for memory locations containing pointer values). The use of such code is called a barrier. Barrier code in garbage collectors often incurs significant runtime overhead.
Garbage collectors, and in particular, concurrent and realtime garbage collectors, often use write- and read-barriers whose code depends on garbage collection phases. A write-barrier is a piece of code that is executed with each memory write operation. Write-barriers may be used for any modifications of memory state, but many garbage collectors use write-barriers only for modification of locations containing pointer values. A read-barrier is a piece of code that is executed with each memory read operation. Read-barriers are especially notorious for reducing program efficiency and are employed only when the benefits are important, such as with real-time garbage collection. For many collectors, and especially concurrent collectors, the barrier overhead is not uniform throughout program execution.
The program execution typically causes the garbage collector to cycle through a set of garbage collection phases, and each phase requires a different set of actions to be taken (e.g., a different behavior of the barrier). Oftentimes there is a substantial idle phase in which the collector is not active and the barrier needs to take no action. When the barrier execution depends on garbage collection phases, the barrier execution typically begins by determining the current phase in order to decide what should be done. This check is generally fast, but the frequency of performing the checks may cause the net effect to be relatively costly, especially if the barrier otherwise is very efficient, or even needs to do nothing else for long periods of times. The phase check is a frequent execution of code that may be unnecessary, can detrimentally impact the in-lining abilities of the compiler, pollute the instruction cache, and consume resources from the branch prediction mechanism.
Conventionally, the garbage collector designer will manually need to address code inefficiencies directly to reduce the cost of memory barriers—by avoiding the use of barriers for common operations (e.g., memory reads), by attempting to remove unnecessary memory barriers from the program via compiler analysis, and/or by aggressively hand-tuning the barrier code.